﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Web.Security;
using vngoodlife.Singleton;
using System.Web.Configuration;
using System.Configuration;
using System.ComponentModel.DataAnnotations;
using System.ComponentModel;
using vngoodlife.Util;


namespace vngoodlife.Models
{

    public class Member_Validation
    {

        //[System.ComponentModel.DataAnnotations.MetadataType(typeof(vngoodlife.Models.Member_Validation))]

        [DisplayName("Tên đăng nhập")]
        [Required(ErrorMessage = "Tên đăng nhập không bỏ trống."), RegularExpression(ConstantClass.testMemberNameRegular_1, ErrorMessage = "Tên đăng nhập từ 6 đến 20 ký tự. Vd: abc_01.11-dd")]
        public virtual string MemberName { get; set; }

        [DisplayName("Phân quyền")]
        public virtual string RoleID { get; set; }

        [DisplayName("Họ và tên")]
        [Required(ErrorMessage = "Họ tên không bỏ trống."), RegularExpression(ConstantClass.testFullNameVietnam, ErrorMessage = "Họ và tên không đúng định dạng tên Việt.")]
        public virtual string FullName { get; set; }

        [DisplayName("Biệt danh")]
        [RegularExpression(ConstantClass.testFullNameVietnam, ErrorMessage = "Biệt danh không đúng định dạng tên Việt.")]
        public virtual string Nick { get; set; }

        [DisplayName("Giới tính")]
        public virtual int GenderID { get; set; }

        [DisplayName("Ngày sinh")]
        [RegularExpression(ConstantClass.testDate_1, ErrorMessage = "Sai định dạng ngày. Ngày sinh có dạng dd/mm/yyyy")]
        public virtual string Birthday { get; set; }

        [DisplayName("Hiện ngày sinh")]
        public virtual bool ShowBirthday { get; set; }

        [DisplayName("Địa chỉ")]
        public virtual string Address { get; set; }

        [Required(ErrorMessage = "Email không bỏ trống."), RegularExpression(ConstantClass.testEmailRegular_1, ErrorMessage = "Không đúng định dạng email.")]
        public virtual string Email { get; set; }

        [DisplayName("Điện thoại")]
        [RegularExpression(ConstantClass.testPhoneRegular_1, ErrorMessage = "Không đúng định dạng số điện thoại.")]
        public virtual string Phone { get; set; }

        [DisplayName("Số chứng minh")]
        [RegularExpression(ConstantClass.testPositiveInteger_2, ErrorMessage = "Không đúng định dạng số chứng minh nhân dân.")]
        public virtual string SocialNumber { get; set; }

        public virtual string Avatar { get; set; }

        [DisplayName("Bài viết cuối đã xem")]
        public virtual string Watch { get; set; }

        [DisplayName("Hiện bài viết cuối đã xem")]
        public virtual bool IsShowWatch { get; set; }

        [DisplayName("Ngày xem bài viết cuối")]
        public virtual DateTime WatchDate { get; set; }

        [DisplayName("Tự giới thiệu")]
        public virtual string Introduction { get; set; }

        [DisplayName("Hiện lời tự giới thiệu")]
        public virtual bool IsShowIntroduction { get; set; }

        [DisplayName("Câu trạng thái")]
        public virtual string MemberStatus { get; set; }

        [DisplayName("Tổng điểm đã nhận")]
        public virtual int TotalMark { get; set; }

        [DisplayName("Tổng điểm đã đổi")]
        public virtual int SoldMark { get; set; }

        [DisplayName("Lần đăng nhập cuối")]
        public virtual DateTime LastLogin { get; set; }

        [DisplayName("Lần đăng xuất cuối")]
        public virtual DateTime LastLogout { get; set; }

        [DisplayName("Ngày tham gia")]
        public virtual DateTime CreateDate { get; set; }

        [DisplayName("Đã điền đầy đủ thông tin")]
        public virtual bool IsFullInformation { get; set; }

        [DisplayName("Hoạt động")]
        public virtual bool IsActive { get; set; }

        [DisplayName("Lần cuối được chỉnh sửa")]
        public virtual DateTime EditDate { get; set; }

        [DisplayName("Người chỉnh sửa cuối")]
        public virtual string UpdateMemberName { get; set; }

    }


        public class LogOnMemberModel
        {
            [Required]
            [DisplayName("Tài khoản")]
            public string UserName { get; set; }

            [Required]
            [DataType(DataType.Password)]
            [DisplayName("Mật khẩu")]
            public string Password { get; set; }

            [DisplayName("Nhớ ?")]
            public bool RememberMe { get; set; }
        }

        #region IFormsAuthenticationService

        public interface IFormsAuthenticationService
        {
            void SignIn(string userName, bool createPersistentCookie);
            void SignOut();
        }

        public class FormsAuthenticationService : IFormsAuthenticationService
        {
            public void SignIn(string userName, bool createPersistentCookie)
            {
                if (String.IsNullOrEmpty(userName)) throw new ArgumentException("Value cannot be null or empty.", "userName");
                //////////
                var roles = new List<string> { };
                string tempRole = DataSingleton.Instance.GetMemberModel().GetMemberRole(userName);
                roles.Add(tempRole);
                //if (tempRole.Equals("C"))
                //{
                //    roles.Add("Manager");
                //}
                //else if (tempRole.Equals("B"))
                //{
                //    roles.Add("Leader");
                //}
                //  SetAuthenticationCookie(userName, role); use for one user has one role
                SetAuthenticationCookie(userName, roles, createPersistentCookie);

                //// original code
                //   FormsAuthentication.SetAuthCookie(userName, createPersistentCookie); 
            }

            //Create an encrypted FormsAuthenticationTicket and store the user roles
            //in pipe delimited format as part of the userData
            //Send down to client in a cookie
            //This will be read back in global.asax
            private void SetAuthenticationCookie(string userName, List<string> roles, bool createPersistentCookie)
            {
                HttpCookiesSection cookieSection = (HttpCookiesSection)ConfigurationManager.GetSection("system.web/httpCookies");
                AuthenticationSection authenticationSection = (AuthenticationSection)ConfigurationManager.GetSection("system.web/authentication");

                FormsAuthenticationTicket authTicket =
                    new FormsAuthenticationTicket(
                    1, userName.ToString(), DateTime.Now, DateTime.Now.AddMinutes(authenticationSection.Forms.Timeout.TotalMinutes),
                    createPersistentCookie, string.Join("|", roles.ToArray()));

                String encryptedTicket = FormsAuthentication.Encrypt(authTicket);
                HttpCookie authCookie = new HttpCookie(FormsAuthentication.FormsCookieName, encryptedTicket);
                                       
                HttpContext.Current.Response.Cookies.Add(authCookie);

              //  authCookie.HttpOnly = true;
                if (createPersistentCookie)
                {
                    authCookie.Expires = DateTime.Now.AddYears(1);
                }
                else
                {
                    authCookie.Expires = DateTime.Now.AddMinutes(ConstantClass.authenCookieTimeLife);
                }
                if (cookieSection.RequireSSL || authenticationSection.Forms.RequireSSL)
                {
                    authCookie.Secure = true;
                }

                //string[] roles2 = authTicket.UserData.Split(new char[] { '|' });
                //FormsIdentity fi = new FormsIdentity(authTicket);
                //HttpContext.Current.User = new System.Security.Principal.GenericPrincipal(fi, roles2);

            }


            public void SignOut()
            {
                FormsAuthentication.SignOut();
            }
        }

        #endregion

        #region IMembershipService

        public interface IMembershipService
        {
            bool ValidateUser(string userName, string password);
        }

        public class AccountMembershipService : IMembershipService
        {
            private readonly MembershipProvider _provider;

            public AccountMembershipService()
                : this(null)
            {
            }

            public AccountMembershipService(MembershipProvider provider)
            {
                _provider = provider ?? Membership.Provider;
            }

            public bool ValidateUser(string userName, string password)
            {
                if (String.IsNullOrEmpty(userName)) throw new ArgumentException("Value cannot be null or empty.", "userName");
                if (String.IsNullOrEmpty(password)) throw new ArgumentException("Value cannot be null or empty.", "password");

                return _provider.ValidateUser(userName, password);
            }
        }

        #endregion

        public class MemberModels
        {
            internal string GetMemberRole(string userName)
            {
                return DataSingleton.Instance.GetLinQContext().Members.Single(u => u.MemberName == userName).RoleID.ToString();
            }

            /// <summary>
            /// Check user and pass is correct or not
            /// </summary>
            /// <param name="username"></param>
            /// <param name="password"></param>
            /// <returns></returns>
            internal bool CheckUserAvailability(string username, string password)
            {
                return DataSingleton.Instance.GetLinQContext().Members.Any(u => u.MemberName == username && u.Pass == password && u.IsActive == true);
            }


            internal void UpdateLogInTime(string username)
            {
                try
                {
                    Member mem = DataSingleton.Instance.GetLinQContext().Members.SingleOrDefault(u => u.MemberName == username);
                    mem.LastLogin = DateTime.Now;
                    DataSingleton.Instance.GetLinQContext().Members.Context.SubmitChanges();
                }
                catch (Exception)
                {
                    DataSingleton.Instance.RefreshInstance();
                }
            }

            internal void UpdateLogOutTime(string username)
            {
                try
                {
                    Member mem = DataSingleton.Instance.GetLinQContext().Members.SingleOrDefault(u => u.MemberName == username);
                    mem.LastLogout = DateTime.Now;
                    DataSingleton.Instance.GetLinQContext().Members.Context.SubmitChanges();
                }
                catch (Exception)
                {
                    DataSingleton.Instance.RefreshInstance();
                }
                
            }


            /// <summary>
            /// Get Admin List in BackEnd
            /// </summary>
            /// <returns></returns>
            internal IQueryable<Member> GetAdminList()
            {
                return DataSingleton.Instance.GetLinQContext().Members.Where(a => ConstantClass.roleIDListOfAdmin.Contains(a.RoleID)).OrderBy(a => a.IsActive); 
            }

            /// <summary>
            /// Insert member and admin into database
            /// </summary>
            /// <param name="admin"></param>
            internal string CreateMember(Member admin, string adminName)
            {
                try
                {
                    string pass = RandomPassword.Generate(ConstantClass._randomPassLength);
                    admin.Pass = GeneralClass.GetMD5Hash(pass);
                    admin.UpdateMemberName = adminName;
                    admin.ShowBirthday = true;
                    admin.IsShowWatch = true;
                    admin.IsShowIntroduction = true;
                    admin.IsActive = true;

                    admin.WatchDate = DateTime.Now;
                    admin.LastLogin = DateTime.Now;
                    admin.LastLogout = DateTime.Now;
                    admin.CreateDate = DateTime.Now;
                    admin.EditDate = DateTime.Now;
                    

                    DataSingleton.Instance.GetLinQContext().Members.InsertOnSubmit(admin);
                    DataSingleton.Instance.GetLinQContext().Members.Context.SubmitChanges();
                    return pass;
                }
                catch (Exception)
                {
                    DataSingleton.Instance.RefreshInstance();
                    return "";
                }
            }

            /// <summary>
            /// Check membername is used or not. True if membername is used and otherwise
            /// </summary>
            /// <param name="p"></param>
            /// <returns></returns>
            internal bool MemberNameIsUsed(string memberName)
            {
                return DataSingleton.Instance.GetLinQContext().Members.Any(m => m.MemberName == memberName);
            }


            /// <summary>
            /// Get a member details
            /// </summary>
            /// <param name="memberName"></param>
            /// <returns></returns>
            internal Member GetMemberDetails(string memberName)
            {
                return DataSingleton.Instance.GetLinQContext().Members.SingleOrDefault(m => m.MemberName == memberName);
            }


            /// <summary>
            /// Update new information of a admin
            /// </summary>
            /// <param name="admin"></param>
            /// <returns></returns>
            internal bool EditAdmin(Member admin, string adminName)
            {
                try
                {
                    Member temmem = DataSingleton.Instance.GetMemberModel().GetMemberDetails(admin.MemberName);
                    
                    temmem.RoleID = admin.RoleID;
                    temmem.FullName = admin.FullName;
                    temmem.Nick = admin.Nick == null ? null : admin.Nick.Trim();
                    temmem.Gender = DataSingleton.Instance.GetLinQContext().Genders.SingleOrDefault(g => g.GenderID == admin.GenderID);
                    temmem.Birthday = admin.Birthday;
                    temmem.ShowBirthday = admin.ShowBirthday;

                    temmem.Address = admin.Address == null ? null : admin.Address.Trim();
                    temmem.Email = admin.Email;
                    temmem.Phone = admin.Phone;
                    temmem.SocialNumber = admin.SocialNumber;
                    temmem.Avatar = admin.Avatar;
                    temmem.Watch = admin.Watch;
                    temmem.IsShowWatch = admin.IsShowWatch;

                    temmem.Introduction = admin.Introduction == null ? null : admin.Introduction.Trim();
                    temmem.IsShowIntroduction = admin.IsShowIntroduction;
                    temmem.MemberStatus = admin.MemberStatus == null ? null : admin.MemberStatus.Trim();
                    temmem.IsFullInformation = admin.IsFullInformation;
                    temmem.IsActive = admin.IsActive;
                    temmem.EditDate = DateTime.Now;
                    temmem.UpdateMemberName = adminName;

                    
                    DataSingleton.Instance.GetLinQContext().Members.Context.SubmitChanges();
                }
                catch (Exception)
                {
                    DataSingleton.Instance.RefreshInstance();
                    return false;
                }
                return true;
            }


            /// <summary>
            /// Random Password for member
            /// </summary>
            /// <param name="memberName"></param>
            /// <returns></returns>
            internal string RandomPassForMember(string memberName, string adminName)
            {
                try
                {
                    Member temMem = DataSingleton.Instance.GetLinQContext().Members.SingleOrDefault(m => m.MemberName == memberName);
                    string pass = RandomPassword.Generate(ConstantClass._randomPassLength);
                    temMem.Pass = GeneralClass.GetMD5Hash(pass);
                    temMem.UpdateMemberName = adminName;
                    temMem.EditDate = DateTime.Now ;

                    DataSingleton.Instance.GetLinQContext().Members.Context.SubmitChanges();
                    return pass;
                }
                catch (Exception)
                {
                    DataSingleton.Instance.RefreshInstance();
                    return "";
                }
            }


            /// <summary>
            /// Check password of member is correct or not. True is correct and otherwise
            /// </summary>
            /// <param name="adminName"></param>
            /// <param name="oldPass"></param>
            /// <returns></returns>
            internal bool IsCorrectPassword(string memberName, string oldPass)
            {
                //string pass = GeneralClass.GetMD5Hash(newPass);
                return DataSingleton.Instance.GetLinQContext().Members.Any(m => m.MemberName == memberName && m.Pass == GeneralClass.GetMD5Hash(oldPass));
            }


            /// <summary>
            /// Change Password for member
            /// </summary>
            /// <param name="memberName"></param>
            /// <returns></returns>
            internal bool ChangePassForMember(string memberName, string newPass)
            {
                try
                {
                    Member temMem = DataSingleton.Instance.GetLinQContext().Members.SingleOrDefault(m => m.MemberName == memberName);
                    temMem.Pass = GeneralClass.GetMD5Hash(newPass);
                    temMem.UpdateMemberName = memberName;
                    temMem.EditDate = DateTime.Now;

                    DataSingleton.Instance.GetLinQContext().Members.Context.SubmitChanges();
                }
                catch (Exception)
                {
                    DataSingleton.Instance.RefreshInstance();
                    return false;
                }
                return true;
            }
        }
    }
